home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Electronic Clipper 1995 April
/
Electronic Clipper 1995-04.iso
/
pc
/
pc_users
/
ideasrc
/
setup
/
pviewer
/
pictkids.c
< prev
next >
Wrap
Text File
|
1993-04-17
|
54KB
|
1,293 lines
// ---------------------------------------------------------------------
//
// PictKids.c - Picture Viewer - QuickTime for Windows
//
// Version 1.0
//
// (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
//
// ---------------------------------------------------------------------
// Includes
// --------
#define NOMINMAX
#include <Windows.H> // Required by Windows
#include <stdlib.h> // Required for abs function
#include <qtole.h> // Interface to qtole dll
#include <qtw.h> // Interface to QuickTime
#include "common.h" // Interface to common.c
#include "viewer.h" // Interface to *.c files
#include "viewer.hr" // Defines used in *.rc files
#include "picture.h" // Interface to picture window
// child window processing
// Constants
// -----------------------
#define BANNER_TEXT_HEIGHT 9 // Banner text height in points
#define TEXT_EXTRA_SPACING 1 // Extra spacing in number text
// Message-Persistent Data
// -----------------------
static struct // Hungarian notation: g
{WORD wScrollBarWidth; // Vertical scroll bar width
WORD wScrollBarHeight; // Horizontal scroll bar height
WORD wBannerBarHeight; // Banner bar height
WORD wZoomWndWidth; // Width of zoom scroll bar window
WORD wMinWndHeight; // Minimum height of window
HBITMAP hbmpGrowBox; // Grow box bitmap
BOOL bLimitGrowBoxResize; // Flag to turn on max resize limits
// using grow box
POINT ptMaxGrowBoxResize; // Max size for grow box resizing
RECT rcResizeRect; // Maximized wnd grow box resize rect
POINT ptCursorOffset; // Offset of cursor from edge of window
// used during maximized wnd grow box resize
} g;
// Exported callback function
// ----------------------------
LONG __export CALLBACK PictureBannerWndProc (HWND, UINT, WPARAM, LPARAM);
// Internal Function Declarations
// ------------------------------
static VOID NEAR UpdateScrollingParms (HWND, NPPICTUREDATA, LPRECT);
static HBITMAP NEAR GetGrowBoxBitmap (HDC, NPPICTUREDATA);
static VOID NEAR DrawTheFrameRect (LPRECT);
// Function: ResizeKids - Resizes the child windows whenever the picture
// window is resized
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture window
// WORD wClientWidth Width of client rect
// WORD wClientHeight Height of client rect
//
// Returns: 0L
// --------------------------------------------------------------------
VOID FAR ResizeKids
( HWND hwndPicture, WORD wClientWidth, WORD wClientHeight )
{NPPICTUREDATA pPictureData; // -> picture data struct
RECT rcPicture; // Picture rect in picture coordinates
HDWP hdwp; // Handle to defer wnd pos struct
int xBrdr; // Width of non resizable border
int yBrdr; // Height of non resizable border
// Note: All the extra terms involving xBrdr and yBrdr are used to make
// the control boundaries match up correctly without heavy lines
// appearing between the controls
xBrdr = GetSystemMetrics( SM_CXBORDER );
yBrdr = GetSystemMetrics( SM_CYBORDER );
if( !(pPictureData =
(NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
{CommonTellUser( ViewerQueryResources(),
VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
return;
}
if( ( hdwp = BeginDeferWindowPos( 5 )) &&
// Zoom window. This control has a constant size
( hdwp = DeferWindowPos( hdwp, pPictureData->zsZoomScroll.hwnd,
NULL,
-xBrdr,
wClientHeight - g.wScrollBarHeight + yBrdr,
g.wZoomWndWidth,
g.wScrollBarHeight,
SWP_NOZORDER )) &&
// Banner bar. This control has a constant height
( hdwp = DeferWindowPos( hdwp, pPictureData->hwndBanner,
NULL,
0,
0,
wClientWidth,
g.wBannerBarHeight,
SWP_NOZORDER )) &&
// Vertical scroll bar. This control has a constant width
( hdwp = DeferWindowPos( hdwp, pPictureData->spmsVScroll.hwnd,
NULL,
wClientWidth - g.wScrollBarWidth + xBrdr,
g.wBannerBarHeight - yBrdr,
g.wScrollBarWidth,
wClientHeight - g.wScrollBarHeight
- g.wBannerBarHeight + 3 * yBrdr,
SWP_NOZORDER )) &&
// Horizontal scroll bar. This control has a constant height
( hdwp = DeferWindowPos( hdwp, pPictureData->spmsHScroll.hwnd,
NULL,
g.wZoomWndWidth - 2 * xBrdr,
wClientHeight - g.wScrollBarHeight + yBrdr,
wClientWidth - g.wZoomWndWidth -
g.wScrollBarWidth + 4 * xBrdr,
g.wScrollBarHeight,
SWP_NOZORDER )))
{EndDeferWindowPos( hdwp );
}
else
{ // Zoom window. This control has a constant size
MoveWindow( pPictureData->zsZoomScroll.hwnd,
-xBrdr, wClientHeight - g.wScrollBarHeight + yBrdr,
g.wZoomWndWidth, g.wScrollBarHeight, TRUE );
// Banner bar. This control has a constant height
MoveWindow( pPictureData->hwndBanner, 0, 0,
wClientWidth, g.wBannerBarHeight, TRUE );
// Vertical scroll bar. This control has a constant width
MoveWindow( pPictureData->spmsVScroll.hwnd,
wClientWidth - g.wScrollBarWidth + xBrdr,
g.wBannerBarHeight - yBrdr, g.wScrollBarWidth,
wClientHeight - g.wScrollBarHeight -
g.wBannerBarHeight + 3 * yBrdr, TRUE );
// Horizontal scroll bar. This control has a constant height
MoveWindow( pPictureData->spmsHScroll.hwnd,
g.wZoomWndWidth - 2 * xBrdr,
wClientHeight - g.wScrollBarHeight + yBrdr,
wClientWidth - g.wZoomWndWidth -
g.wScrollBarWidth + 4 * xBrdr,
g.wScrollBarHeight, TRUE );
}
pPictureData->rcGrowBox.left = wClientWidth -
g.wScrollBarWidth + 2 * xBrdr;
pPictureData->rcGrowBox.top = wClientHeight -
g.wScrollBarHeight + 2 * yBrdr;
pPictureData->rcGrowBox.right = wClientWidth;
pPictureData->rcGrowBox.bottom = wClientHeight;
rcPicture.left = rcPicture.top = 0;
rcPicture.right = wClientWidth;
rcPicture.bottom = wClientHeight;
PictureRectFromClient( &rcPicture );
UpdateScrollingParms( hwndPicture, pPictureData, &rcPicture );
// Force these to get painted now to avoid long delay while
// waiting for the picture to be painted. This improves the
// appearance of the window during resizing
UpdateWindow( pPictureData->zsZoomScroll.hwnd );
UpdateWindow( pPictureData->hwndBanner );
UpdateWindow( pPictureData->spmsHScroll.hwnd );
UpdateWindow( pPictureData->spmsVScroll.hwnd );
return;
}
// Function: CreateViewerKids - Creates the child windows for the picture
// window
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture window
// NPPICTUREDATA pPictureData -> to picture data struct
//
// Returns: LONG 0l if OK
// --------------------------------------------------------------------
LONG FAR CreateViewerKids( HWND hwndPicture, NPPICTUREDATA pPictureData )
{WORD wIDError; // Resource error string id
g.wScrollBarWidth = (WORD) GetSystemMetrics( SM_CXVSCROLL );
g.wScrollBarHeight = (WORD) GetSystemMetrics( SM_CYHSCROLL );
g.wBannerBarHeight = (WORD) GetSystemMetrics( SM_CYMENU );
g.wMinWndHeight = (WORD) ( GetSystemMetrics( SM_CYCAPTION ) +
g.wBannerBarHeight + g.wScrollBarHeight +
3 * GetSystemMetrics( SM_CYVSCROLL ));
wIDError = VIEWER_STRING_NOMEMORY;
if( !( pPictureData->spmsHScroll.hwnd =
CreateWindow( "scrollbar", NULL,
WS_CHILD | WS_VISIBLE | SBS_HORZ,
0, 0, 0, 0, hwndPicture,
(HMENU) PICTURE_HORZ_SCROLL,
ViewerQueryInstance(), NULL )))
{goto Failed;
}
if( !(pPictureData->spmsVScroll.hwnd =
CreateWindow( "scrollbar", NULL,
WS_CHILD | WS_VISIBLE | SBS_VERT,
0, 0, 0, 0, hwndPicture,
(HMENU) PICTURE_VERT_SCROLL,
ViewerQueryInstance(), NULL )))
{goto Failed;
}
// Try initial width. This may be adjusted during create processing
if( !( pPictureData->zsZoomScroll.hwnd =
CreateWindow( PICTURE_ZOOM_CLASS, NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER,
0, 0, 6 * GetSystemMetrics( SM_CXHSCROLL ),
g.wScrollBarHeight, hwndPicture,
(HMENU) PICTURE_ZOOM_SCROLL,
ViewerQueryInstance(), NULL )))
{goto Failed;
}
else // Set the global variable here because dimensions may have
// been adjusted. Use the query because GetClientRect() won't
// work until after first call to MoveWindow() and we need
// width before then.
{g.wZoomWndWidth = ViewerQueryZoomWndWidth();
}
if( !( pPictureData->hwndBanner =
CreateWindow( PICTURE_BANNER_CLASS, NULL,
WS_CHILD | WS_VISIBLE,
0, 0, 0, 0, hwndPicture,
(HMENU) PICTURE_BANNER,
ViewerQueryInstance(), NULL )))
{goto Failed;
}
// this window does nothing so disable it
EnableWindow( pPictureData->hwndBanner, FALSE );
return 0L;
Failed:
CommonTellUser( ViewerQueryResources(), wIDError, NULL, MB_OK );
return MAKELONG( wIDError, 0 );
}
// Function: ZoomPicture - Resizes the Picture to the input width and
// height
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of Picture window
// WORD wZoomIndex Index of desired zoom
//
// Returns: LONG 0L if successful
// --------------------------------------------------------------------
LONG FAR ZoomPicture( HWND hwndPicture, WORD wZoomIndex )
{NPPICTUREDATA pPictureData; // -> picture data struct
RECT rcMaxPicture; // Current max picture display area
WORD wZoomMult; // Zoom multiplier factor
if( !(pPictureData =
(NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
{CommonTellUser( ViewerQueryResources(),
VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
return VIEWER_STRING_NOPICDATA;
}
if( pPictureData->zsZoomScroll.wCurZoomIndex == wZoomIndex )
return 0L;
pPictureData->rcCurPictureRect.left = 0;
pPictureData->rcCurPictureRect.top = 0;
wZoomMult = ViewerQueryZoomMultiplier( wZoomIndex );
pPictureData->rcCurPictureRect.right =
MulDiv( pPictureData->idImageInfo.width, wZoomMult, 100 );
pPictureData->rcCurPictureRect.bottom =
MulDiv( pPictureData->idImageInfo.height, wZoomMult, 100 );
// Get client rect
GetClientRect( hwndPicture, &rcMaxPicture );
// Convert to Picture coordinates
PictureRectFromClient( &rcMaxPicture );
// This routine also offsets rcCurPictureRect when necessary
UpdateScrollingParms( hwndPicture, pPictureData, &rcMaxPicture );
// Update buckle ...
pPictureData->zsZoomScroll.wCurZoomIndex = wZoomIndex;
if( IsWindowVisible( pPictureData->zsZoomScroll.hwnd ))
SendMessage( pPictureData->zsZoomScroll.hwnd,
WM_ZOOM_MOVEBUCKLE, (WPARAM) wZoomIndex, 0L );
// ... and paint
InvalidateRect( hwndPicture, NULL, TRUE);
if( pPictureData->hwndGetInfo )
SendMessage( pPictureData->hwndGetInfo,
WM_INFO_CURRENTSIZE, 0, 0L );
return 0L;
}
// Function: ClientRectFromPicture - Returns the client rect in client
// coordinates that corresponds to the
// input picture rect in picture coords.
// --------------------------------------------------------------------
// Parameters: LPRECT lprc -> Picture rect on input
//
// Returns: VOID lprc -> Client rect on output
// --------------------------------------------------------------------
VOID FAR ClientRectFromPicture( LPRECT lprc )
{
lprc->right -= lprc->left;
lprc->bottom -= lprc->top;
lprc->left = lprc->top = 0;
lprc->right += g.wScrollBarWidth -
GetSystemMetrics( SM_CXBORDER );
lprc->bottom += g.wScrollBarHeight + g.wBannerBarHeight -
GetSystemMetrics( SM_CYBORDER );
return;
}
// Function: PictureRectFromClient - Returns the maximum picture rect
// in picture coordinates corresponding
// to the input client rect in
// client coords
// --------------------------------------------------------------------
// Parameters: LPRECT lprc -> Client rect on input
//
// Returns: VOID lprc -> Max Picture rect on output
// --------------------------------------------------------------------
VOID FAR PictureRectFromClient( LPRECT lprc )
{
lprc->right -= lprc->left;
lprc->bottom -= lprc->top;
lprc->left = lprc->top = 0;
lprc->right -= g.wScrollBarWidth -
GetSystemMetrics( SM_CXBORDER );
lprc->bottom -= g.wScrollBarHeight + g.wBannerBarHeight -
GetSystemMetrics( SM_CYBORDER );
return;
}
// Function: ClientToPicture - Converts from client to picture coordinates
// --------------------------------------------------------------------
// Parameters: LPPOINT lppt -> points
// WORD wNum Number of points to convert
//
// Returns: VOID
// --------------------------------------------------------------------
VOID FAR ClientToPicture( LPPOINT lppt, WORD wNum )
{WORD i; // Counter
for(i=0; i < wNum; i++, lppt++)
lppt->y -= g.wBannerBarHeight;
return;
}
// Function: PictureToClient - Converts from picture to client coordinates
// --------------------------------------------------------------------
// Parameters: LPPOINT lppt -> points
// WORD wNum number of points to convert
//
// Returns: VOID
// --------------------------------------------------------------------
VOID FAR PictureToClient( LPPOINT lppt, WORD wNum )
{WORD i; // Counter
for(i=0; i < wNum; i++, lppt++)
lppt->y += g.wBannerBarHeight;
return;
}
// Function: SetMinMaxInfo - Processes the picture window
// WM_GETMINMAXINFO message
// --------------------------------------------------------------------
// Parameters: MINMAXINFO FAR* lpmmi -> to minmaxinfo struct
//
// Returns: LONG always 0L
// --------------------------------------------------------------------
LONG FAR SetMinMaxInfo( MINMAXINFO FAR* lpmmi )
{
lpmmi->ptMinTrackSize.x = g.wZoomWndWidth +
5 * GetSystemMetrics( SM_CXHSCROLL );
lpmmi->ptMinTrackSize.y = g.wMinWndHeight;
if( g.bLimitGrowBoxResize )
{lpmmi->ptMaxTrackSize = g.ptMaxGrowBoxResize;
}
return 0L;
}
// Function: UpdateScrollingParms - Update the scroll bar parameters after
// size of picture is changed
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture window
// NPPICTUREDATA pPictureData -> picture data struct
// LPRECT lprcMaxPicture -> to to picture display
// area of wnd
//
// Returns: VOID
// --------------------------------------------------------------------
static VOID NEAR UpdateScrollingParms( HWND hwndPicture,
NPPICTUREDATA pPictureData, LPRECT lprcMaxPicture )
{WORD wCurPictWidth; // Current picture width
WORD wCurPictHeight; // Current picture height
WORD wOldMax; // Previous max scroll value
WORD wDisplayWidth; // Display width, i.e. area available
// for display of picture
WORD wDisplayHeight; // Display height
wCurPictWidth = pPictureData->rcCurPictureRect.right -
pPictureData->rcCurPictureRect.left;
wCurPictHeight = pPictureData->rcCurPictureRect.bottom -
pPictureData->rcCurPictureRect.top;
wDisplayWidth = lprcMaxPicture->right - lprcMaxPicture->left;
wDisplayHeight = lprcMaxPicture->bottom - lprcMaxPicture->top;
// leave these fixed
pPictureData->spmsHScroll.wCurLine = g.wScrollBarWidth;
pPictureData->spmsVScroll.wCurLine = g.wScrollBarHeight;
// Adjust these for size of window
pPictureData->spmsHScroll.wCurPage = wDisplayWidth - 1;
pPictureData->spmsVScroll.wCurPage = wDisplayHeight - 1;
// Set horizontal scrollbar parms
if( wDisplayWidth >= wCurPictWidth )
{pPictureData->spmsHScroll.wCurPos = 0;
pPictureData->spmsHScroll.wCurMax = 0;
EnableWindow( pPictureData->spmsHScroll.hwnd, FALSE );
}
else
{wOldMax = pPictureData->spmsHScroll.wCurMax;
pPictureData->spmsHScroll.wCurMax =
wCurPictWidth - wDisplayWidth;
// Scale current position for new display area
if( wOldMax > 0 )
pPictureData->spmsHScroll.wCurPos =
MulDiv( pPictureData->spmsHScroll.wCurPos,
pPictureData->spmsHScroll.wCurMax, wOldMax );
else
pPictureData->spmsHScroll.wCurPos = 0;
EnableWindow( pPictureData->spmsHScroll.hwnd, TRUE );
SetScrollRange( pPictureData->spmsHScroll.hwnd, SB_CTL,
0, pPictureData->spmsHScroll.wCurMax, FALSE );
SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
pPictureData->spmsHScroll.wCurPos, TRUE );
}
// Set vertical scrollbar parms
if( wDisplayHeight >= wCurPictHeight )
{pPictureData->spmsVScroll.wCurPos = 0;
pPictureData->spmsVScroll.wCurMax = 0;
EnableWindow( pPictureData->spmsVScroll.hwnd, FALSE );
}
else
{wOldMax = pPictureData->spmsVScroll.wCurMax;
pPictureData->spmsVScroll.wCurMax =
wCurPictHeight - wDisplayHeight;
// Scale current position for new display area
if( wOldMax > 0 )
pPictureData->spmsVScroll.wCurPos =
MulDiv( pPictureData->spmsVScroll.wCurPos,
pPictureData->spmsVScroll.wCurMax, wOldMax );
else
pPictureData->spmsVScroll.wCurPos = 0;
EnableWindow( pPictureData->spmsVScroll.hwnd, TRUE );
SetScrollRange( pPictureData->spmsVScroll.hwnd, SB_CTL,
0, pPictureData->spmsVScroll.wCurMax, FALSE );
SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
pPictureData->spmsVScroll.wCurPos, TRUE );
}
// Define ->rcCurPictureRect. The point (0, 0) is always the Upper-Left
// corner of the display area. Therefore, rcCur.. .left and .top are
// negative if the picture is scrolled.
pPictureData->rcCurPictureRect.left =
- ((int) pPictureData->spmsHScroll.wCurPos);
pPictureData->rcCurPictureRect.top =
- ((int) pPictureData->spmsVScroll.wCurPos);
pPictureData->rcCurPictureRect.right =
pPictureData->rcCurPictureRect.left + wCurPictWidth;
pPictureData->rcCurPictureRect.bottom =
pPictureData->rcCurPictureRect.top + wCurPictHeight;
return;
}
// Function: ProcessHorzScroll - Process horizontal scroll bar messages
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture window
// WORD wScrollCode Scroll code as defined in windows.h
// int nCurBoxPos Current position of scroll box
//
// Returns: LONG 0L if OK
// --------------------------------------------------------------------
LONG FAR ProcessHorzScroll
(HWND hwndPicture, WORD wScrollCode, int nCurBoxPos )
{NPPICTUREDATA pPictureData; // -> picture data struct
int nPosition; // Temp scroll position
WORD wWidth; // Picture width
int nToScroll; // Amount to scroll
RECT rcPictArea; // Picture rect in client coordinates
if( !(pPictureData =
(NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
{CommonTellUser( ViewerQueryResources(),
VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
return VIEWER_STRING_NOPICDATA;
}
if( !IsWindowEnabled( pPictureData->spmsHScroll.hwnd ))
return 0L;
nPosition = pPictureData->spmsHScroll.wCurPos;
switch( wScrollCode )
{case SB_PAGERIGHT:
nPosition += pPictureData->spmsHScroll.wCurPage;
break;
case SB_LINERIGHT:
nPosition += pPictureData->spmsHScroll.wCurLine;
break;
case SB_PAGELEFT:
nPosition -= pPictureData->spmsHScroll.wCurPage;
break;
case SB_LINELEFT:
nPosition -= pPictureData->spmsHScroll.wCurLine;
break;
case SB_LEFT:
nPosition = 0;
break;
case SB_RIGHT:
nPosition = pPictureData->spmsHScroll.wCurMax;
break;
case SB_THUMBPOSITION:
nPosition = (WORD) nCurBoxPos;
break;
default:
break;
}
nPosition = min( max( 0, nPosition ),
(int) pPictureData->spmsHScroll.wCurMax );
if( nPosition != (int) pPictureData->spmsHScroll.wCurPos )
{nToScroll = nPosition - pPictureData->spmsHScroll.wCurPos;
pPictureData->spmsHScroll.wCurPos = nPosition;
wWidth = pPictureData->rcCurPictureRect.right -
pPictureData->rcCurPictureRect.left;
pPictureData->rcCurPictureRect.left = -nPosition;
pPictureData->rcCurPictureRect.right = -nPosition + wWidth;
SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
pPictureData->spmsHScroll.wCurPos, TRUE );
// Get picture rect in picture coordinates
GetClientRect( hwndPicture, &rcPictArea );
PictureRectFromClient( &rcPictArea);
// Convert to client coordinates for ScrollWindow
PictureToClient( (LPPOINT) &rcPictArea, 2 );
if( ((WORD) abs( nToScroll )) <
pPictureData->spmsHScroll.wCurPage )
{UpdateWindow( hwndPicture );
ScrollWindow( hwndPicture, -nToScroll, 0,
&rcPictArea, &rcPictArea );
}
else
InvalidateRect( hwndPicture, &rcPictArea, TRUE );
UpdateWindow( hwndPicture );
}
return 0L;
}
// Function: ProcessVertScroll - Process vertical scroll bar messages
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture window
// WORD wScrollCode Scroll code as defined in windows.h
// int nCurBoxPos Current position of scroll box
//
// Returns: LONG 0L if OK
// --------------------------------------------------------------------
LONG FAR ProcessVertScroll
(HWND hwndPicture, WORD wScrollCode, int nCurBoxPos )
{NPPICTUREDATA pPictureData; // -> picture data struct
int nPosition; // Temp scroll position
WORD wHeight; // Picture height
int nToScroll; // Amount to scroll
RECT rcPictArea; // Picture rect in client coordinates
if( !(pPictureData =
(NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
{CommonTellUser( ViewerQueryResources(),
VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
return VIEWER_STRING_NOPICDATA;
}
if( !IsWindowEnabled( pPictureData->spmsVScroll.hwnd ))
return 0L;
nPosition = pPictureData->spmsVScroll.wCurPos;
switch( wScrollCode )
{case SB_PAGEDOWN:
nPosition += pPictureData->spmsVScroll.wCurPage;
break;
case SB_LINEDOWN:
nPosition += pPictureData->spmsVScroll.wCurLine;
break;
case SB_PAGEUP:
nPosition -= pPictureData->spmsVScroll.wCurPage;
break;
case SB_LINEUP:
nPosition -= pPictureData->spmsVScroll.wCurLine;
break;
case SB_TOP:
nPosition = 0;
break;
case SB_BOTTOM:
nPosition = pPictureData->spmsVScroll.wCurMax;
break;
case SB_THUMBPOSITION:
nPosition = nCurBoxPos;
break;
default:
break;
}
nPosition = min( max( 0, nPosition ),
(int) pPictureData->spmsVScroll.wCurMax );
if( nPosition != (int) pPictureData->spmsVScroll.wCurPos )
{nToScroll = nPosition - pPictureData->spmsVScroll.wCurPos;
pPictureData->spmsVScroll.wCurPos = nPosition;
wHeight = pPictureData->rcCurPictureRect.bottom -
pPictureData->rcCurPictureRect.top;
pPictureData->rcCurPictureRect.top = -nPosition;
pPictureData->rcCurPictureRect.bottom = -nPosition + wHeight;
SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
pPictureData->spmsVScroll.wCurPos, TRUE );
// Get picture rect in picture coordinates
GetClientRect( hwndPicture, &rcPictArea );
PictureRectFromClient( &rcPictArea);
// Convert to client coordinates for ScrollWindow
PictureToClient( (LPPOINT) &rcPictArea, 2 );
if( ((WORD) abs( nToScroll )) <
pPictureData->spmsVScroll.wCurPage )
{UpdateWindow( hwndPicture );
ScrollWindow( hwndPicture, 0, -nToScroll,
&rcPictArea, &rcPictArea );
}
else
InvalidateRect( hwndPicture, &rcPictArea, TRUE );
UpdateWindow( hwndPicture );
}
return 0L;
}
// Function: ScrollToCorner - Scroll to upper_left or lower-right corner
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture window
// WORD wScrollCode Scroll code as defined in windows.h
//
// Returns: LONG 0L if OK
// --------------------------------------------------------------------
LONG FAR ScrollToCorner(HWND hwndPicture, WORD vk_key )
{NPPICTUREDATA pPictureData; // -> picture data struct
int nHorzPosition; // Temp horz scroll position
int nVertPosition; // Temp vert scroll position
WORD wWidth; // Picture width
WORD wHeight; // Picture height
int nHorzToScroll; // Amount to scroll horz
int nVertToScroll; // Amount to scroll vert
RECT rcPictArea; // Picture rect in client coordinates
if( !(pPictureData =
(NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
{CommonTellUser( ViewerQueryResources(),
VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
return VIEWER_STRING_NOPICDATA;
}
if( vk_key == VK_HOME )
nVertPosition = nHorzPosition = 0;
else
{nHorzPosition = pPictureData->spmsHScroll.wCurMax;
nVertPosition = pPictureData->spmsVScroll.wCurMax;
}
nHorzToScroll = nHorzPosition - (int) pPictureData->spmsHScroll.wCurPos;
nVertToScroll = nVertPosition - (int) pPictureData->spmsVScroll.wCurPos;
if( nHorzToScroll || nVertToScroll )
{pPictureData->spmsHScroll.wCurPos = nHorzPosition;
pPictureData->spmsVScroll.wCurPos = nVertPosition;
wWidth = pPictureData->rcCurPictureRect.right -
pPictureData->rcCurPictureRect.left;
pPictureData->rcCurPictureRect.left = -nHorzPosition;
pPictureData->rcCurPictureRect.right = -nHorzPosition + wWidth;
wHeight = pPictureData->rcCurPictureRect.bottom -
pPictureData->rcCurPictureRect.top;
pPictureData->rcCurPictureRect.top = -nVertPosition;
pPictureData->rcCurPictureRect.bottom = -nVertPosition + wHeight;
if( IsWindowEnabled( pPictureData->spmsHScroll.hwnd ))
SetScrollPos( pPictureData->spmsHScroll.hwnd, SB_CTL,
pPictureData->spmsHScroll.wCurPos, TRUE );
if( IsWindowEnabled( pPictureData->spmsVScroll.hwnd ))
SetScrollPos( pPictureData->spmsVScroll.hwnd, SB_CTL,
pPictureData->spmsVScroll.wCurPos, TRUE );
// Get picture rect in picture coordinates
GetClientRect( hwndPicture, &rcPictArea );
PictureRectFromClient( &rcPictArea);
// Convert to client coordinates for ScrollWindow
PictureToClient( (LPPOINT) &rcPictArea, 2 );
if( (((WORD) abs( nHorzToScroll )) <
pPictureData->spmsHScroll.wCurPage ) &&
(((WORD) abs( nVertToScroll )) <
pPictureData->spmsVScroll.wCurPage ))
{UpdateWindow( hwndPicture );
ScrollWindow( hwndPicture, -nHorzToScroll, -nVertToScroll,
&rcPictArea, &rcPictArea );
}
else
InvalidateRect( hwndPicture, &rcPictArea, TRUE );
UpdateWindow( hwndPicture );
}
return 0L;
}
// Function: IsInGrowBox - Determines if the cursor is in the grow box
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture wnd
// POINT ptCursor Cursor position in client coords.
//
// Returns: BOOL TRUE if in grow box, else FALSE
// --------------------------------------------------------------------
BOOL FAR IsInGrowBox( HWND hwndPicture, POINT ptCursor )
{NPPICTUREDATA pPictureData; // -> picture data struct
if( !(pPictureData =
(NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) ||
!PtInRect( &pPictureData->rcGrowBox, ptCursor ))
return FALSE;
else
return TRUE;
}
// Function: DestroyGrowBoxBitmap - Destroys the grow box bitnmap
// --------------------------------------------------------------------
// Parameters: VOID
//
// Returns: VOID
// --------------------------------------------------------------------
VOID FAR DestroyGrowBoxBitmap( VOID )
{if( g.hbmpGrowBox )
{DeleteObject( g.hbmpGrowBox );
g.hbmpGrowBox = NULL;
}
return;
}
// Function: PaintTheGrowBox - Paints the grow box
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture window
// HDC hdc DC of picture window
// NPPICTUREDATA pPictureData -> picture wnd data struct
//
// Returns: VOID
// --------------------------------------------------------------------
VOID FAR PaintTheGrowBox( HWND hwndPicture,
HDC hdc, NPPICTUREDATA pPictureData )
{HDC hmemDC; // Memory dc
HBITMAP hbmpSave; // Prev bitmap
HBRUSH hbrushSave; // Background brush
if( !g.hbmpGrowBox &&
!(g.hbmpGrowBox = GetGrowBoxBitmap( hdc, pPictureData )))
return;
if( IsZoomed( hwndPicture ) && IsZoomed( ViewerQueryFrameWindow()))
{if( hbrushSave = SelectObject( hdc, GetStockObject( LTGRAY_BRUSH )))
{PatBlt( hdc,
pPictureData->rcGrowBox.left,
pPictureData->rcGrowBox.top,
pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left,
pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top,
PATCOPY );
SelectObject( hdc, hbrushSave );
}
}
else
{hmemDC = NULL;
if( ( hmemDC = CreateCompatibleDC( hdc )) &&
( hbmpSave = SelectObject( hmemDC, g.hbmpGrowBox )))
{BitBlt( hdc,
pPictureData->rcGrowBox.left,
pPictureData->rcGrowBox.top,
pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left,
pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top,
hmemDC, 0, 0, SRCCOPY );
SelectObject( hmemDC, hbmpSave );
}
if( hmemDC )
DeleteDC( hmemDC );
}
return;
}
// Function: GetGrowBoxBitmap - Create the grow box mem bitmap. This routine
// saves a bitmap of the correct size so that
// bitblt can be used to draw the bitmap instead
// stetchblt which is much slower
// --------------------------------------------------------------------
// Parameters: HDC hdc DC of picture window
// NPPICTUREDATA pPictureData -> picture wnd data struct
//
// Returns: HBITMAP hbmpGrowBox Handle of grow box mem bitmap
// --------------------------------------------------------------------
static HBITMAP NEAR GetGrowBoxBitmap( HDC hdc, NPPICTUREDATA pPictureData )
{HDC hmemDC1; // Mem dc
HDC hmemDC2; // Mem dc
BITMAP bm; // bitmap struct
HBITMAP hbmp; // Handle of resource bitmap
HBITMAP hbmpSave1; // Prev bitmap
HBITMAP hbmpSave2; // Prev bitmap
HBITMAP hbmpGrowBox; // Handle of grow box bitmap
int nWidth; // Width of final bitmap
int nHeight; // Height of final bitmap
HBRUSH hbrushSave; // Prev brush
int xOffset; // x bitmap offset
int yOffset; // y bitmap offset
if( !( hbmp = LoadBitmap( ViewerQueryResources(),
MAKEINTRESOURCE( VIEWER_GROWBOX_BITMAP ))))
return NULL;
hmemDC1 = hmemDC2 = NULL;
nWidth = pPictureData->rcGrowBox.right - pPictureData->rcGrowBox.left;
nHeight = pPictureData->rcGrowBox.bottom - pPictureData->rcGrowBox.top;
if( ( hmemDC1 = CreateCompatibleDC( hdc )) &&
( hmemDC2 = CreateCompatibleDC( hdc )) &&
( hbmpGrowBox = CreateCompatibleBitmap
( hdc, nWidth, nHeight )))
{hbmpSave1 = SelectObject( hmemDC1, hbmp );
hbmpSave2 = SelectObject( hmemDC2, hbmpGrowBox );
// set the background to light gray
hbrushSave = SelectObject( hmemDC2, GetStockObject( LTGRAY_BRUSH ));
PatBlt( hmemDC2, 0, 0, nWidth, nHeight, PATCOPY );
SelectObject( hmemDC2, hbrushSave );
GetObject( hbmp, sizeof( BITMAP ), &bm );
xOffset = ( nWidth - bm.bmWidth ) / 2;
yOffset = ( nHeight - bm.bmHeight ) / 2;
BitBlt( hmemDC2, max( 0, xOffset ), max( 0, yOffset ),
min( bm.bmWidth, nWidth ),
min( bm.bmHeight, nHeight ),
hmemDC1,
max( 0, -xOffset ),
max( 0, -yOffset ), SRCCOPY );
SelectObject( hmemDC1, hbmpSave1 );
SelectObject( hmemDC2, hbmpSave2 );
}
if( hmemDC1 )
DeleteDC( hmemDC1 );
if( hmemDC2 )
DeleteDC( hmemDC2 );
DeleteObject( hbmp );
return hbmpGrowBox;
}
// Function: LimitTheDragSize - Limits the resized of the window so that it stays
// inside the MDI client rect. Used with grow box
// processing
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture hwnd of picture window
// BOOL bDragging TRUE if dragging using grow box
//
// Returns: VOID
// --------------------------------------------------------------------
VOID FAR LimitTheDragSize( HWND hwndPicture, BOOL bDragging )
{RECT rcClient; // Client rect of MDI client
RECT rcwndPicture; // Window rect of picture wnd
if( !( g.bLimitGrowBoxResize = bDragging ))
return;
if( !IsZoomed( hwndPicture ))
{GetWindowRect( hwndPicture, &rcwndPicture );
GetClientRect( ViewerQueryClientWindow(), &rcClient );
MapWindowPoints( HWND_DESKTOP, ViewerQueryClientWindow(),
(LPPOINT) &rcwndPicture, 2 );
g.ptMaxGrowBoxResize.x = rcClient.right - rcwndPicture.left;
g.ptMaxGrowBoxResize.y = rcClient.bottom - rcwndPicture.top;
}
return;
}
// Function: InitMaxWndGrowBoxResize - Initializes the maximized window grow
// box resizing
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture wnd
// POINT ptCursor Position of cursor
//
// Returns: BOOL TRUE if successful
// --------------------------------------------------------------------
BOOL FAR InitMaxWndGrowBoxResize( HWND hwndPicture, POINT ptCursor )
{RECT rcClipCursor; // Clip cursor rect
HDC hdc; // DC of desktop
GetWindowRect( ViewerQueryFrameWindow(), &g.rcResizeRect );
ClientToScreen( hwndPicture, &ptCursor );
g.ptCursorOffset.x = g.rcResizeRect.right - ptCursor.x;
g.ptCursorOffset.y = g.rcResizeRect.bottom - ptCursor.y;
rcClipCursor.left = g.rcResizeRect.left +
GetSystemMetrics( SM_CXMINTRACK ) - g.ptCursorOffset.x;
rcClipCursor.top = g.rcResizeRect.top +
GetSystemMetrics( SM_CYMINTRACK ) - g.ptCursorOffset.y;
if( hdc = GetDC( NULL ))
{rcClipCursor.right =
GetDeviceCaps( hdc, HORZRES ) - g.ptCursorOffset.x;
rcClipCursor.bottom =
GetDeviceCaps( hdc, VERTRES ) - g.ptCursorOffset.y;
ReleaseDC( NULL, hdc );
}
else
{rcClipCursor.right = 0x7fff;
rcClipCursor.bottom = 0x7fff;
}
ClipCursor( &rcClipCursor );
DrawTheFrameRect( &g.rcResizeRect );
return TRUE;
}
// Function: MoveTheFrameRect - Moves the resizing rect during maximized
// window grow box resizing
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture wnd
// POINT ptCursor Position of cursor
//
// Returns: VOID
// --------------------------------------------------------------------
VOID FAR MoveTheFrameRect( HWND hwndPicture, POINT ptCursor )
{DrawTheFrameRect( &g.rcResizeRect );
ClientToScreen( hwndPicture, &ptCursor );
g.rcResizeRect.right = ptCursor.x + g.ptCursorOffset.x;
g.rcResizeRect.bottom = ptCursor.y + g.ptCursorOffset.y;
DrawTheFrameRect( &g.rcResizeRect );
return;
}
// Function: EndMaxWndGrowBoxResize - Terminates the maximized window grow
// box resizing
// --------------------------------------------------------------------
// Parameters: HWND hwndPicture Handle of picture wnd
//
// Returns: VOID
// --------------------------------------------------------------------
VOID FAR EndMaxWndGrowBoxResize( HWND hwndPicture )
{DrawTheFrameRect( &g.rcResizeRect );
DrawTheFrameRect( NULL ); // Does clean up
ClipCursor( NULL );
MoveWindow( ViewerQueryFrameWindow(),
g.rcResizeRect.left, g.rcResizeRect.top,
g.rcResizeRect.right - g.rcResizeRect.left,
g.rcResizeRect.bottom - g.rcResizeRect.top, TRUE );
return;
}
// Function: DrawTheFrameRect - Draws the resizing frame
// --------------------------------------------------------------------
// Parameters: RECT lprcResizeRect -> resize rect
//
// Returns: VOID
// --------------------------------------------------------------------
static VOID NEAR DrawTheFrameRect( LPRECT lprcResizeRect )
{HDC hdc; // DC of desktop
HBRUSH hbrushSave; // Prev brush
HBITMAP hbitmapCheckers; // Handle of checkerboard bitmap
typedef BOOL ( CALLBACK* FFRAMEPROC ) (HDC, LPRECT, int, int, DWORD);
static WORD wBorderWidth; // Width of vertical resize border
static WORD wBorderHeight; // Height of horizontal resize border
static FFRAMEPROC lpfnFastWindowFrame; // -> FastWindowFrame()
static HBRUSH hbrushCheckers; // Handle to frame brush
// FastWindowFrame() is an undocumented Windows function
// described in "Undocumented Windows" by Andrew Schulman,
// David Maxey and Matt Pietrek, Addison Wesley, 1992.
if( lprcResizeRect == NULL ) // Clean up
{if( hbrushCheckers )
{DeleteObject( hbrushCheckers );
hbrushCheckers = NULL;
}
return;
}
if( !lpfnFastWindowFrame )
{lpfnFastWindowFrame = (FFRAMEPROC) GetProcAddress(
GetModuleHandle( "GDI" ), "FASTWINDOWFRAME" );
wBorderWidth = GetSystemMetrics( SM_CXFRAME ) - 1;
wBorderHeight = GetSystemMetrics( SM_CXFRAME ) - 1;
}
if( !hbrushCheckers &&
( hbitmapCheckers = LoadBitmap( ViewerQueryInstance(),
MAKEINTRESOURCE( VIEWER_CHECKERS_BITMAP ))))
{hbrushCheckers = CreatePatternBrush( hbitmapCheckers );
DeleteObject( hbitmapCheckers );
}
if( hdc = GetDC( NULL ))
{if( lpfnFastWindowFrame )
{
if( hbrushCheckers )
hbrushSave = SelectObject( hdc, hbrushCheckers );
else
hbrushSave = SelectObject( hdc,
GetStockObject( GRAY_BRUSH ));
if( !( *lpfnFastWindowFrame ) ( hdc, lprcResizeRect,
wBorderWidth, wBorderHeight, PATINVERT ))
{ // Use PatBlt when FastWindowFrame fails
ExcludeClipRect( hdc,
lprcResizeRect->left + wBorderWidth,
lprcResizeRect->top + wBorderHeight,
lprcResizeRect->right - wBorderWidth,
lprcResizeRect->bottom - wBorderHeight );
PatBlt( hdc, lprcResizeRect->left,
lprcResizeRect->top,
lprcResizeRect->right - lprcResizeRect->left,
lprcResizeRect->bottom - lprcResizeRect->top,
PATINVERT );
}
if( hbrushSave )
SelectObject( hdc, hbrushSave );
}
else
{DrawFocusRect( hdc, lprcResizeRect );
}
ReleaseDC( NULL, hdc );
}
return;
}
// Function: PictureBannerWndProc - Window proc for the banner child window
// --------------------------------------------------------------------
// Parameters: As required by Microsoft Windows
//
// Returns: Via DefWindowProc
// --------------------------------------------------------------------
LONG __export CALLBACK PictureBannerWndProc
(HWND hwndBanner, UINT message, WPARAM wParam, LPARAM lParam)
{NPPICTUREDATA pPictureData; // -> picture data struct
PAINTSTRUCT ps; // Paint struct
RECT rcClient; // Client rect of control
UINT nSaveAlign; // Prev text align
WORD wBaseLine; // Base line for text output
HFONT hFont; // Handle of font
HFONT hsaveFont; // Handle of prev font
int nHeight; // Height of font
if( message == WM_PAINT )
{if( !(pPictureData = (NPPICTUREDATA) GetWindowWord
( GetParent( hwndBanner ), 0 )))
return 0L;
if( !BeginPaint( hwndBanner, &ps ))
return 0L;
GetClientRect( hwndBanner, &rcClient );
MoveTo( ps.hdc, 0, rcClient.bottom - 1 );
LineTo( ps.hdc, rcClient.right, rcClient.bottom - 1 );
// Don't report an error if this fails since it will just
// use the system font instead
nHeight = -MulDiv( BANNER_TEXT_HEIGHT,
GetDeviceCaps( ps.hdc, LOGPIXELSY ), 72 );
hsaveFont = NULL;
if( hFont = MakeAnArialFont( ps.hdc, nHeight ))
hsaveFont = SelectObject( ps.hdc, hFont );
wBaseLine = 3 * rcClient.bottom / 4;
nSaveAlign = SetTextAlign( ps.hdc, TA_LEFT | TA_BASELINE );
TextOut( ps.hdc, 6, wBaseLine, pPictureData->szPictType,
lstrlen( pPictureData->szPictType ));
SetTextAlign( ps.hdc, TA_RIGHT | TA_BASELINE );
SetTextCharacterExtra( ps.hdc,
GetTextCharacterExtra( ps.hdc ) + TEXT_EXTRA_SPACING );
TextOut( ps.hdc, rcClient.right - 6, wBaseLine,
pPictureData->szFileSize,
lstrlen( pPictureData->szFileSize ));
SetTextAlign( ps.hdc, nSaveAlign );
if( hsaveFont )
SelectObject( ps.hdc, hsaveFont );
if( hFont )
DeleteObject( hFont );
EndPaint( hwndBanner, &ps );
return 0L;
}
else
return DefWindowProc( hwndBanner, message, wParam, lParam);
}
// Function: MakeAnArialFont - Creates a logical font
// --------------------------------------------------------------------
// Parameters: HDC hdc Device context
// int nTextSize Size of font
//
// Returns: HFONT hFont
// Note: It is up to the caller to eventually delete this font
// --------------------------------------------------------------------
HFONT FAR MakeAnArialFont( HDC hdc, int nTextSize )
{HFONT hFont; // Handle to created font
PLOGFONT plf; // -> to font struct
if( !( plf = (PLOGFONT) LocalAlloc( LPTR, sizeof( LOGFONT ))))
return NULL;
plf->lfHeight = nTextSize;
plf->lfWeight = FW_LIGHT;
plf->lfOutPrecision = OUT_TT_ONLY_PRECIS;
plf->lfPitchAndFamily = FF_SWISS;
LoadString( ViewerQueryResources(), VIEWER_STRING_FACENAME,
plf->lfFaceName, sizeof( plf->lfFaceName ));
hFont = CreateFontIndirect( plf );
LocalFree( (LOCALHANDLE) plf );
return hFont;
}
// Function: RegisterChildControls - Registers the window classes for the
// picture resizing and banner child windows
// --------------------------------------------------------------------
// Parameters: HINSTANCE hInstance Instance of application
//
// Returns: BOOL TRUE if OK
// --------------------------------------------------------------------
BOOL FAR RegisterChildControls( HINSTANCE hInstance )
{WNDCLASS wc; // Window class information
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = PictureZoomWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH) ( COLOR_BTNFACE + 1 );
wc.lpszMenuName = NULL;
wc.lpszClassName = PICTURE_ZOOM_CLASS;
if( !RegisterClass( &wc ))
return FALSE;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = PictureBannerWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = GetStockObject( WHITE_BRUSH );
wc.lpszMenuName = NULL;
wc.lpszClassName = PICTURE_BANNER_CLASS;
return RegisterClass( &wc );
}